#!/bin/bash

# ====================================================================================
# JDK 自动化安装与部署一体化脚本
#
# 描述:
#   此脚本集部署与安装于一体。在主控节点运行后，它会自动将 JDK 安装包
#   分发到所有目标服务器，并远程执行安装和环境配置。
#
# 前提条件:
#   1. 以 root 用户身份运行此脚本。
#   2. 必须配置好到所有目标节点的免密SSH登录。
#   3. JDK 的 .tar.gz 安装包必须与此脚本位于同一目录下。
# ====================================================================================

# --- 脚本配置 ---
set -euo pipefail

# --- 用户配置区 ---
readonly TARGET_NODES=("srvdb1" "srvdb2" "srvdb3")
readonly JDK_PACKAGE="microsoft-jdk-11.0.27-linux-x64.tar.gz" # !! 请确保文件名正确
readonly INSTALL_DIR="/usr/local/java"
readonly JAVA_SYMLINK_PATH="/opt/jdk11" # 将创建此软链接作为统一的 JAVA_HOME
readonly REMOTE_USER="root"
readonly REMOTE_TEMP_DIR="/root/install_temp_$$" # $$ 表示当前进程ID，确保临时目录唯一

# --- 函数定义 ---
log_info() { echo -e "\033[32m[INFO] $1\033[0m"; }
log_error() { echo -e "\033[31m[ERROR] $1\033[0m" >&2; }


# ====================================================================================
#   ↓↓↓ 这是被远程执行的核心安装函数 ↓↓↓
# ====================================================================================
perform_jdk_installation() {
    # 这个函数将在远程服务器上被执行

    # 遇到任何错误立即退出
    set -euo pipefail

    # --- 函数内部变量 ---
    # 第一个参数是远程服务器上 JDK 安装包的完整路径
    local remote_jdk_package_path=$1 
    # 从完整路径中提取出文件名
    local jdk_tarball=$(basename "$remote_jdk_package_path")
    # 这两个变量从主脚本传递过来
    local install_dir=$2
    local java_symlink_path=$3

    # --- 函数逻辑 ---
    log_info " [远程] 开始执行 JDK 安装..."

    # 动态获取解压后的目录名
    local jdk_extracted_dir=$(tar -tf "$remote_jdk_package_path" | head -n 1 | cut -d'/' -f1)
    local java_home_path="${install_dir}/${jdk_extracted_dir}"

    # 安全检查
    if [ -d "$java_home_path" ] || [ -e "$java_symlink_path" ]; then
        log_error " [远程] 错误：目标目录 ${java_home_path} 或软链接 ${java_symlink_path} 已存在。"
        exit 1
    fi

    # 创建目录并解压
    log_info " [远程] 正在创建目录并解压..."
    mkdir -p "$install_dir"
    tar -xzf "$remote_jdk_package_path" -C "$install_dir"
    if [[ ! -d "$java_home_path" ]]; then log_error " [远程] 解压失败！"; exit 1; fi

    # 创建符号链接
    log_info " [远程] 正在创建符号链接 ${java_symlink_path}..."
    ln -s "$java_home_path" "$java_symlink_path"

    # 配置环境变量
    log_info " [远程] 正在配置系统环境变量..."
    cat > "/etc/profile.d/jdk.sh" <<EOF
# JDK Environment Variables
export JAVA_HOME=${java_symlink_path}
export PATH=\$JAVA_HOME/bin:\$PATH
EOF
    chmod +x "/etc/profile.d/jdk.sh"
    
    log_info " [远程] ✅ JDK 安装配置成功！"
}
# ====================================================================================
#   ↑↑↑ 核心安装函数定义结束 ↑↑↑
# ====================================================================================


# --- 主逻辑 (总指挥) ---
log_info "🚀 开始向所有目标节点部署 JDK..."

if [[ ! -f "$JDK_PACKAGE" ]]; then log_error "错误：JDK安装包 '$JDK_PACKAGE' 在本地未找到！"; exit 1; fi

# 将函数定义导出为字符串，以便通过 ssh 传递
# declare -f 会打印出函数的完整定义
exported_functions=$(declare -f perform_jdk_installation log_info log_error)

# 遍历所有目标节点
for node in "${TARGET_NODES[@]}"; do
    echo "--------------------------------------------------"
    log_info "正在处理节点: ${node}"

    # 1. 分发 JDK 安装包
    log_info " -> 步骤 1/3: 正在分发文件到 ${node}..."
    ssh ${REMOTE_USER}@${node} "mkdir -p ${REMOTE_TEMP_DIR}"
    scp "${JDK_PACKAGE}" "${REMOTE_USER}@${node}:${REMOTE_TEMP_DIR}/"
    log_info " -> 文件分发完成。"

    # 2. 远程执行安装函数
    log_info " -> 步骤 2/3: 正在远程执行安装..."
    # 通过 ssh 将函数定义和调用命令一起传递给远程服务器
    if ssh ${REMOTE_USER}@${node} "
        # 在远程服务器上重新定义这些函数
        ${exported_functions}
        
        # 然后调用函数，并传递必要的参数
        perform_jdk_installation '${REMOTE_TEMP_DIR}/${JDK_PACKAGE}' '${INSTALL_DIR}' '${JAVA_SYMLINK_PATH}'
    "; then
        log_info " -> ✅ 节点 ${node} 部署成功！"
    else
        log_error " -> ❌ 节点 ${node} 部署失败！请检查上面的日志输出。"
        log_error "部署脚本已终止。"
        exit 1
    fi

    # 3. 清理远程临时文件
    log_info " -> 步骤 3/3: 正在清理远程临时文件..."
    ssh ${REMOTE_USER}@${node} "rm -rf ${REMOTE_TEMP_DIR}"
    log_info " -> 清理完成。"
done

echo "--------------------------------------------------"
log_info "🎉 所有节点的 JDK 均已成功部署！"
